﻿using System;
using System.IO;
using System.IO.Ports;
using System.Text;
using System.Threading;
using HslCommunication.Core;
using HslCommunication.LogNet;
using HslCommunication.Reflection;

namespace HslCommunication.Serial
{
	/// <summary>
	/// 所有串行通信类的基类，提供了一些基础的服务，核心的通信实现<br />
	/// The base class of all serial communication classes provides some basic services for the core communication implementation
	/// </summary>
	// Token: 0x02000029 RID: 41
	public class SerialBase : IDisposable
	{
		/// <summary>
		/// 实例化一个无参的构造方法<br />
		/// Instantiate a parameterless constructor
		/// </summary>
		// Token: 0x0600028A RID: 650 RVA: 0x0000A360 File Offset: 0x00008560
		public SerialBase()
		{
			this.sP_ReadData = new SerialPort();
			this.hybirdLock = new SimpleHybirdLock();
		}

		/// <summary>
		/// 初始化串口信息，9600波特率，8位数据位，1位停止位，无奇偶校验<br />
		/// Initial serial port information, 9600 baud rate, 8 data bits, 1 stop bit, no parity
		/// </summary>
		/// <param name="portName">端口号信息，例如"COM3"</param>
		// Token: 0x0600028B RID: 651 RVA: 0x0000A3C1 File Offset: 0x000085C1
		public void SerialPortInni(string portName)
		{
			this.SerialPortInni(portName, 9600);
		}

		/// <summary>
		/// 初始化串口信息，波特率，8位数据位，1位停止位，无奇偶校验<br />
		/// Initializes serial port information, baud rate, 8-bit data bit, 1-bit stop bit, no parity
		/// </summary>
		/// <param name="portName">端口号信息，例如"COM3"</param>
		/// <param name="baudRate">波特率</param>
		// Token: 0x0600028C RID: 652 RVA: 0x0000A3D0 File Offset: 0x000085D0
		public void SerialPortInni(string portName, int baudRate)
		{
			this.SerialPortInni(portName, baudRate, 8, StopBits.One, Parity.None);
		}

		/// <summary>
		/// 初始化串口信息，波特率，数据位，停止位，奇偶校验需要全部自己来指定<br />
		/// Start serial port information, baud rate, data bit, stop bit, parity all need to be specified
		/// </summary>
		/// <param name="portName">端口号信息，例如"COM3"</param>
		/// <param name="baudRate">波特率</param>
		/// <param name="dataBits">数据位</param>
		/// <param name="stopBits">停止位</param>
		/// <param name="parity">奇偶校验</param>
		// Token: 0x0600028D RID: 653 RVA: 0x0000A3E0 File Offset: 0x000085E0
		public void SerialPortInni(string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity)
		{
			bool isOpen = this.sP_ReadData.IsOpen;
			if (!isOpen)
			{
				this.sP_ReadData.PortName = portName;
				this.sP_ReadData.BaudRate = baudRate;
				this.sP_ReadData.DataBits = dataBits;
				this.sP_ReadData.StopBits = stopBits;
				this.sP_ReadData.Parity = parity;
				this.PortName = this.sP_ReadData.PortName;
				this.BaudRate = this.sP_ReadData.BaudRate;
			}
		}

		/// <summary>
		/// 根据自定义初始化方法进行初始化串口信息<br />
		/// Initialize the serial port information according to the custom initialization method
		/// </summary>
		/// <param name="initi">初始化的委托方法</param>
		// Token: 0x0600028E RID: 654 RVA: 0x0000A468 File Offset: 0x00008668
		public void SerialPortInni(Action<SerialPort> initi)
		{
			bool isOpen = this.sP_ReadData.IsOpen;
			if (!isOpen)
			{
				this.sP_ReadData.PortName = "COM5";
				this.sP_ReadData.BaudRate = 9600;
				this.sP_ReadData.DataBits = 8;
				this.sP_ReadData.StopBits = StopBits.One;
				this.sP_ReadData.Parity = Parity.None;
				initi(this.sP_ReadData);
				this.PortName = this.sP_ReadData.PortName;
				this.BaudRate = this.sP_ReadData.BaudRate;
			}
		}

		/// <summary>
		/// 打开一个新的串行端口连接<br />
		/// Open a new serial port connection
		/// </summary>
		// Token: 0x0600028F RID: 655 RVA: 0x0000A504 File Offset: 0x00008704
		public OperateResult Open()
		{
			OperateResult result;
			try
			{
				bool flag = !this.sP_ReadData.IsOpen;
				if (flag)
				{
					this.sP_ReadData.Open();
					result = this.InitializationOnOpen();
				}
				else
				{
					result = OperateResult.CreateSuccessResult();
				}
			}
			catch (Exception ex)
			{
				bool flag2 = this.connectErrorCount < 100000000;
				if (flag2)
				{
					this.connectErrorCount++;
				}
				result = new OperateResult(-this.connectErrorCount, ex.Message);
			}
			return result;
		}

		/// <summary>
		/// 获取一个值，指示串口是否处于打开状态<br />
		/// Gets a value indicating whether the serial port is open
		/// </summary>
		/// <returns>是或否</returns>
		// Token: 0x06000290 RID: 656 RVA: 0x0000A58C File Offset: 0x0000878C
		public bool IsOpen()
		{
			return this.sP_ReadData.IsOpen;
		}

		/// <summary>
		/// 关闭当前的串口连接<br />
		/// Close the current serial connection
		/// </summary>
		// Token: 0x06000291 RID: 657 RVA: 0x0000A59C File Offset: 0x0000879C
		public void Close()
		{
			bool isOpen = this.sP_ReadData.IsOpen;
			if (isOpen)
			{
				this.ExtraOnClose();
				this.sP_ReadData.Close();
			}
		}

		/// <summary>
		/// 将原始的字节数据发送到串口，然后从串口接收一条数据。<br />
		/// The raw byte data is sent to the serial port, and then a piece of data is received from the serial port.
		/// </summary>
		/// <param name="send">发送的原始字节数据</param>
		/// <returns>带接收字节的结果对象</returns>
		// Token: 0x06000292 RID: 658 RVA: 0x0000A5D0 File Offset: 0x000087D0
		[HslMqttApi(Description = "The raw byte data is sent to the serial port, and then a piece of data is received from the serial port.")]
		public OperateResult<byte[]> ReadBase(byte[] send)
		{
			return this.ReadBase(send, false);
		}

		/// <summary>
		/// 将原始的字节数据发送到串口，然后从串口接收一条数据。<br />
		/// The raw byte data is sent to the serial port, and then a piece of data is received from the serial port.
		/// </summary>
		/// <param name="send">发送的原始字节数据</param>
		/// <param name="sendOnly">是否只是发送，如果为true, 不需要等待数据返回，如果为false, 需要等待数据返回</param>
		/// <returns>带接收字节的结果对象</returns>
		// Token: 0x06000293 RID: 659 RVA: 0x0000A5EC File Offset: 0x000087EC
		public OperateResult<byte[]> ReadBase(byte[] send, bool sendOnly)
		{
			ILogNet logNet = this.LogNet;
			if (logNet != null)
			{
				logNet.WriteDebug(this.ToString(), StringResources.Language.Send + " : " + (this.LogMsgFormatBinary ? send.ToHexString(' ') : Encoding.ASCII.GetString(send)));
			}
			this.hybirdLock.Enter();
			OperateResult operateResult = this.Open();
			bool flag = !operateResult.IsSuccess;
			OperateResult<byte[]> result;
			if (flag)
			{
				this.hybirdLock.Leave();
				result = OperateResult.CreateFailedResult<byte[]>(operateResult);
			}
			else
			{
				bool flag2 = this.IsClearCacheBeforeRead;
				if (flag2)
				{
					this.ClearSerialCache();
				}
				OperateResult operateResult2 = this.SPSend(this.sP_ReadData, send);
				bool flag3 = !operateResult2.IsSuccess;
				if (flag3)
				{
					this.hybirdLock.Leave();
					result = OperateResult.CreateFailedResult<byte[]>(operateResult2);
				}
				else if (sendOnly)
				{
					this.hybirdLock.Leave();
					result = OperateResult.CreateSuccessResult<byte[]>(new byte[0]);
				}
				else
				{
					OperateResult<byte[]> operateResult3 = this.SPReceived(this.sP_ReadData, true);
					this.hybirdLock.Leave();
					ILogNet logNet2 = this.LogNet;
					if (logNet2 != null)
					{
						logNet2.WriteDebug(this.ToString(), StringResources.Language.Receive + " : " + (this.LogMsgFormatBinary ? operateResult3.Content.ToHexString(' ') : Encoding.ASCII.GetString(operateResult3.Content)));
					}
					result = operateResult3;
				}
			}
			return result;
		}

		/// <summary>
		/// 清除串口缓冲区的数据，并返回该数据，如果缓冲区没有数据，返回的字节数组长度为0<br />
		/// The number sent clears the data in the serial port buffer and returns that data, or if there is no data in the buffer, the length of the byte array returned is 0
		/// </summary>
		/// <returns>是否操作成功的方法</returns>
		// Token: 0x06000294 RID: 660 RVA: 0x0000A75E File Offset: 0x0000895E
		public OperateResult<byte[]> ClearSerialCache()
		{
			return this.SPReceived(this.sP_ReadData, false);
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.InitializationOnConnect(System.Net.Sockets.Socket)" />
		// Token: 0x06000295 RID: 661 RVA: 0x0000A76D File Offset: 0x0000896D
		protected virtual OperateResult InitializationOnOpen()
		{
			return OperateResult.CreateSuccessResult();
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkDoubleBase.ExtraOnDisconnect(System.Net.Sockets.Socket)" />
		// Token: 0x06000296 RID: 662 RVA: 0x0000A76D File Offset: 0x0000896D
		protected virtual OperateResult ExtraOnClose()
		{
			return OperateResult.CreateSuccessResult();
		}

		/// <summary>
		/// 发送数据到串口去。<br />
		/// Send data to serial port.
		/// </summary>
		/// <param name="serialPort">串口对象</param>
		/// <param name="data">字节数据</param>
		/// <returns>是否发送成功</returns>
		// Token: 0x06000297 RID: 663 RVA: 0x0000A774 File Offset: 0x00008974
		protected virtual OperateResult SPSend(SerialPort serialPort, byte[] data)
		{
			bool flag = data != null && data.Length != 0;
			if (flag)
			{
				bool flag2 = !Authorization.nzugaydgwadawdibbas();
				if (flag2)
				{
					return new OperateResult<byte[]>(StringResources.Language.AuthorizationFailed);
				}
				try
				{
					serialPort.Write(data, 0, data.Length);
					return OperateResult.CreateSuccessResult();
				}
				catch (Exception ex)
				{
					bool flag3 = this.connectErrorCount < 100000000;
					if (flag3)
					{
						this.connectErrorCount++;
					}
					return new OperateResult(-this.connectErrorCount, ex.Message);
				}
			}
			return OperateResult.CreateSuccessResult();
		}

		/// <summary>
		/// 从串口接收一串字节数据信息，直到没有数据为止，如果参数awaitData为false, 第一轮接收没有数据则返回<br />
		/// Receives a string of bytes of data information from the serial port until there is no data, and returns if the parameter awaitData is false
		/// </summary>
		/// <param name="serialPort">串口对象</param>
		/// <param name="awaitData">是否必须要等待数据返回</param>
		/// <returns>结果数据对象</returns>
		// Token: 0x06000298 RID: 664 RVA: 0x0000A818 File Offset: 0x00008A18
		protected virtual OperateResult<byte[]> SPReceived(SerialPort serialPort, bool awaitData)
		{
			bool flag = !Authorization.nzugaydgwadawdibbas();
			OperateResult<byte[]> result;
			if (flag)
			{
				result = new OperateResult<byte[]>(StringResources.Language.AuthorizationFailed);
			}
			else
			{
				byte[] array = new byte[1024];
				MemoryStream memoryStream = new MemoryStream();
				DateTime now = DateTime.Now;
				for (;;)
				{
					Thread.Sleep(this.sleepTime);
					try
					{
						bool flag2 = serialPort.BytesToRead < 1;
						if (flag2)
						{
							bool flag3 = (DateTime.Now - now).TotalMilliseconds > (double)this.ReceiveTimeout;
							if (flag3)
							{
								memoryStream.Dispose();
								bool flag4 = this.connectErrorCount < 100000000;
								if (flag4)
								{
									this.connectErrorCount++;
								}
								return new OperateResult<byte[]>(-this.connectErrorCount, string.Format("Time out: {0}", this.ReceiveTimeout));
							}
							bool flag5 = memoryStream.Length > 0L;
							if (flag5)
							{
								break;
							}
							if (!awaitData)
							{
								break;
							}
						}
						else
						{
							int count = serialPort.Read(array, 0, array.Length);
							memoryStream.Write(array, 0, count);
						}
					}
					catch (Exception ex)
					{
						memoryStream.Dispose();
						bool flag6 = this.connectErrorCount < 100000000;
						if (flag6)
						{
							this.connectErrorCount++;
						}
						return new OperateResult<byte[]>(-this.connectErrorCount, ex.Message);
					}
				}
				byte[] value = memoryStream.ToArray();
				memoryStream.Dispose();
				this.connectErrorCount = 0;
				result = OperateResult.CreateSuccessResult<byte[]>(value);
			}
			return result;
		}

		/// <inheritdoc cref="P:HslCommunication.Core.Net.NetworkBase.LogNet" />
		// Token: 0x17000093 RID: 147
		// (get) Token: 0x06000299 RID: 665 RVA: 0x0000A9B4 File Offset: 0x00008BB4
		// (set) Token: 0x0600029A RID: 666 RVA: 0x0000A9CC File Offset: 0x00008BCC
		public ILogNet LogNet
		{
			get
			{
				return this.logNet;
			}
			set
			{
				this.logNet = value;
			}
		}

		/// <summary>
		/// 获取或设置一个值，该值指示在串行通信中是否启用请求发送 (RTS) 信号。<br />
		/// Gets or sets a value indicating whether the request sending (RTS) signal is enabled in serial communication.
		/// </summary>
		// Token: 0x17000094 RID: 148
		// (get) Token: 0x0600029B RID: 667 RVA: 0x0000A9D6 File Offset: 0x00008BD6
		// (set) Token: 0x0600029C RID: 668 RVA: 0x0000A9E3 File Offset: 0x00008BE3
		[HslMqttApi(Description = "Gets or sets a value indicating whether the request sending (RTS) signal is enabled in serial communication.")]
		public bool RtsEnable
		{
			get
			{
				return this.sP_ReadData.RtsEnable;
			}
			set
			{
				this.sP_ReadData.RtsEnable = value;
			}
		}

		/// <summary>
		/// 接收数据的超时时间，默认5000ms<br />
		/// Timeout for receiving data, default is 5000ms
		/// </summary>
		// Token: 0x17000095 RID: 149
		// (get) Token: 0x0600029D RID: 669 RVA: 0x0000A9F4 File Offset: 0x00008BF4
		// (set) Token: 0x0600029E RID: 670 RVA: 0x0000AA0C File Offset: 0x00008C0C
		[HslMqttApi(Description = "Timeout for receiving data, default is 5000ms")]
		public int ReceiveTimeout
		{
			get
			{
				return this.receiveTimeout;
			}
			set
			{
				this.receiveTimeout = value;
			}
		}

		/// <summary>
		/// 连续串口缓冲数据检测的间隔时间，默认20ms，该值越小，通信速度越快，但是越不稳定。<br />
		/// Continuous serial port buffer data detection interval, the default 20ms, the smaller the value, the faster the communication, but the more unstable.
		/// </summary>
		// Token: 0x17000096 RID: 150
		// (get) Token: 0x0600029F RID: 671 RVA: 0x0000AA18 File Offset: 0x00008C18
		// (set) Token: 0x060002A0 RID: 672 RVA: 0x0000AA30 File Offset: 0x00008C30
		[HslMqttApi(Description = "Continuous serial port buffer data detection interval, the default 20ms, the smaller the value, the faster the communication, but the more unstable.")]
		public int SleepTime
		{
			get
			{
				return this.sleepTime;
			}
			set
			{
				bool flag = value > 0;
				if (flag)
				{
					this.sleepTime = value;
				}
			}
		}

		/// <summary>
		/// 是否在发送数据前清空缓冲数据，默认是false<br />
		/// Whether to empty the buffer before sending data, the default is false
		/// </summary>
		// Token: 0x17000097 RID: 151
		// (get) Token: 0x060002A1 RID: 673 RVA: 0x0000AA50 File Offset: 0x00008C50
		// (set) Token: 0x060002A2 RID: 674 RVA: 0x0000AA68 File Offset: 0x00008C68
		[HslMqttApi(Description = "Whether to empty the buffer before sending data, the default is false")]
		public bool IsClearCacheBeforeRead
		{
			get
			{
				return this.isClearCacheBeforeRead;
			}
			set
			{
				this.isClearCacheBeforeRead = value;
			}
		}

		/// <summary>
		/// 当前连接串口信息的端口号名称<br />
		/// The port name of the current connection serial port information
		/// </summary>
		// Token: 0x17000098 RID: 152
		// (get) Token: 0x060002A3 RID: 675 RVA: 0x0000AA72 File Offset: 0x00008C72
		// (set) Token: 0x060002A4 RID: 676 RVA: 0x0000AA7A File Offset: 0x00008C7A
		[HslMqttApi(Description = "The port name of the current connection serial port information")]
		public string PortName { get; private set; }

		/// <summary>
		/// 当前连接串口信息的波特率<br />
		/// Baud rate of current connection serial port information
		/// </summary>
		// Token: 0x17000099 RID: 153
		// (get) Token: 0x060002A5 RID: 677 RVA: 0x0000AA83 File Offset: 0x00008C83
		// (set) Token: 0x060002A6 RID: 678 RVA: 0x0000AA8B File Offset: 0x00008C8B
		[HslMqttApi(Description = "Baud rate of current connection serial port information")]
		public int BaudRate { get; private set; }

		/// <summary>
		/// 释放当前的对象
		/// </summary>
		/// <param name="disposing">是否在</param>
		// Token: 0x060002A7 RID: 679 RVA: 0x0000AA94 File Offset: 0x00008C94
		protected virtual void Dispose(bool disposing)
		{
			bool flag = !this.disposedValue;
			if (flag)
			{
				if (disposing)
				{
					SimpleHybirdLock simpleHybirdLock = this.hybirdLock;
					if (simpleHybirdLock != null)
					{
						simpleHybirdLock.Dispose();
					}
					SerialPort serialPort = this.sP_ReadData;
					if (serialPort != null)
					{
						serialPort.Dispose();
					}
				}
				this.disposedValue = true;
			}
		}

		/// <summary>
		/// 释放当前的对象
		/// </summary>
		// Token: 0x060002A8 RID: 680 RVA: 0x0000AAE3 File Offset: 0x00008CE3
		public void Dispose()
		{
			this.Dispose(true);
		}

		/// <inheritdoc />
		// Token: 0x060002A9 RID: 681 RVA: 0x0000AAF0 File Offset: 0x00008CF0
		public override string ToString()
		{
			return string.Format("SerialBase[{0},{1},{2},{3},{4}]", new object[]
			{
				this.sP_ReadData.PortName,
				this.sP_ReadData.BaudRate,
				this.sP_ReadData.DataBits,
				this.sP_ReadData.StopBits,
				this.sP_ReadData.Parity
			});
		}

		/// <inheritdoc cref="F:HslCommunication.Core.Net.NetworkDoubleBase.LogMsgFormatBinary" />
		// Token: 0x040000D7 RID: 215
		protected bool LogMsgFormatBinary = true;

		// Token: 0x040000DA RID: 218
		private bool disposedValue = false;

		/// <summary>
		/// 串口交互的核心
		/// </summary>
		// Token: 0x040000DB RID: 219
		protected SerialPort sP_ReadData = null;

		// Token: 0x040000DC RID: 220
		private SimpleHybirdLock hybirdLock;

		// Token: 0x040000DD RID: 221
		private ILogNet logNet;

		// Token: 0x040000DE RID: 222
		private int receiveTimeout = 5000;

		// Token: 0x040000DF RID: 223
		private int sleepTime = 20;

		// Token: 0x040000E0 RID: 224
		private bool isClearCacheBeforeRead = false;

		// Token: 0x040000E1 RID: 225
		private int connectErrorCount = 0;
	}
}
